#pragma once
#include "TestHarness.h"
#include "CallPutPair.h"

#include <cmath>

namespace
{
    const double epsilon = 0.00001;
    bool doubleEquals(double left, double right ) {
      return (fabs(left - right) < epsilon);
    }

    bool doubleLess(double left, double right, bool orequal = false) {
      if (fabs(left - right) < epsilon) {
        return (orequal);
      }
      return (left < right);
    }

    bool doubleGreater(double left, double right, bool orequal = false) {
      if (fabs(left - right) < epsilon) {
        return (orequal);
      }
      return (left > right);
    }
}

TEST( CallPutPair, Test )
{
    // call strike price < put strike price
    {
        Warrant call( "5", Warrant::call, "14146", 82.88, 0.069, 10 );
        Warrant put( "5", Warrant::put, "26722", 90, 0.29, 100 );
        CallPutPair subject( call, put );

        CHECK( doubleEquals( subject.GetCost(), -22.57 ) );
        CHECK( doubleEquals( subject.GetRangeStart(), 60.31 ) );
        CHECK( doubleEquals( subject.GetRangeEnd(), 112.57 ) );
    }

    {
        Warrant call( "5", Warrant::call, "14485", 65, 0.61, 10 );
        Warrant put( "5", Warrant::put, "23097", 76.86, 0.136, 100 );
        CallPutPair subject( call, put );

        CHECK( doubleEquals( subject.GetCost(), -7.84 ) );
        CHECK( doubleEquals( subject.GetRangeStart(), 57.16 ) );
        CHECK( doubleEquals( subject.GetRangeEnd(), 84.7 ) );
    }

    {
        Warrant call( "5", Warrant::call, "22780", 68.88, 0.035, 100 );
        Warrant put( "5", Warrant::put, "24489", 76.86, 0.147, 100 );
        CallPutPair subject( call, put );

        CHECK( doubleEquals( subject.GetCost(), -10.22 ) );
        CHECK( doubleEquals( subject.GetRangeStart(), 58.66 ) );
        CHECK( doubleEquals( subject.GetRangeEnd(), 87.08 ) );
    }

    // call strike price > put strike price
    {
        Warrant call( "5", Warrant::call, "11576", 83.8, 0.015, 10 );
        Warrant put( "5", Warrant::put, "23261", 76.88, 0.14, 100 );
        CallPutPair subject( call, put );

        CHECK( doubleEquals( subject.GetCost(), -14.15 ) );
        CHECK( doubleEquals( subject.GetRangeStart(), 62.73 ) );
        CHECK( doubleEquals( subject.GetRangeEnd(), 97.95 ) );
    }
    {
        Warrant call( "5", Warrant::call, "12388", 77.88, 0.028, 10 );
        Warrant put( "5", Warrant::put, "29728", 76, 1.36, 10 );
        CallPutPair subject( call, put );

        CHECK( doubleEquals( subject.GetCost(), -13.88 ) );
        CHECK( doubleEquals( subject.GetRangeStart(), 62.12 ) );
        CHECK( doubleEquals( subject.GetRangeEnd(), 91.76 ) );
    }
    {
        Warrant call( "5", Warrant::call, "15549", 86.926, 0.01, 100 );
        Warrant put( "5", Warrant::put, "12397", 78.88, 1.57, 10 );
        CallPutPair subject( call, put );

        CHECK( doubleEquals( subject.GetCost(), -16.7 ) );
        CHECK( doubleEquals( subject.GetRangeStart(), 62.18 ) );
        CHECK( doubleEquals( subject.GetRangeEnd(), 103.626 ) );
    }
}
